package name.luojun.DBhelper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
public class UpgradeManager {
	public static final String COVER = "cover";
	public static final String ADD = "add";
	public static final String INSERTORUPDATE = "insertOrUpdate";
	private static Logger log = Logger.getLogger(UpgradeManager.class);
	public static void createUpgradeFile(List<?> list, String path) throws Exception {
		File output = new File(path);
		if (output.exists()) {
			output.delete();
		}
		output.getParentFile().mkdirs();
		output.createNewFile();
		FileOutputStream fos = new FileOutputStream(output);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(list);
		oos.flush();
		fos.close();
	}
	@SuppressWarnings({"unchecked"})
	public static void FileUpgrade(Object o, Class<?> c, Class<?> p, InputStream ins, String get, String insert, String modify,
			String delete, String[] identify, String[] fields, String rule) throws Exception {
		Method getMethod = o.getClass().getMethod(get);
		ObjectInputStream oins = new ObjectInputStream(ins);
		List<Object> local = (List<Object>) oins.readObject();
		ins.close();
		Method modifyMethod = o.getClass().getMethod(modify, p);
		Method deleteMethod = o.getClass().getMethod(delete, p);
		Method insertMethod = o.getClass().getMethod(insert, p);
		List<Object> db = (List<Object>) getMethod.invoke(o, null);
		List<Object> create;
		List<Object> update;
		List<Field> fieldlist = new ArrayList<Field>();
		List<Field> pklist = new ArrayList<Field>();
		for (String f : fields) {
			Field field = c.getDeclaredField(f);
			field.setAccessible(true);
			fieldlist.add(field);
		}
		for (String f : identify) {
			Field field = c.getDeclaredField(f);
			field.setAccessible(true);
			pklist.add(field);
		}
		if (rule.equalsIgnoreCase(UpgradeManager.COVER)) {
			for (Object obj : db) {
				deleteMethod.invoke(o, obj);
			}
			for (Object obj : local) {
				insertMethod.invoke(o, obj);
			}
		} else if (rule.equalsIgnoreCase(UpgradeManager.ADD)) {
			create = UpgradeManager.getInsert(local, db, pklist);
			for (Object obj : create) {
				insertMethod.invoke(o, obj);
			}
		} else if (rule.equalsIgnoreCase(UpgradeManager.INSERTORUPDATE)) {
			create = UpgradeManager.getInsert(local, db, pklist);
			for (Object obj : create) {
				insertMethod.invoke(o, obj);
			}
			update = UpgradeManager.getUpdate(local, db, pklist, fieldlist);
			for (Object obj : update) {
				modifyMethod.invoke(o, obj);
			}
		}
	}
	public static void FileUpgradeForSimpleMap(Object o, Class<?> p, InputStream ins, String get, String insert, String modify,
			String delete, String[] identify, String[] fields, String rule) throws Exception {
		Method getMethod = o.getClass().getMethod(get);
		ObjectInputStream oins = new ObjectInputStream(ins);
		List<Object> local = (List<Object>) oins.readObject();
		ins.close();
		Method modifyMethod = o.getClass().getMethod(modify, p);
		Method deleteMethod = o.getClass().getMethod(delete, p);
		Method insertMethod = o.getClass().getMethod(insert, p);
		List<Object> db = (List<Object>) getMethod.invoke(o, null);
		List<Object> create;
		List<Object> update;
		if (rule.equalsIgnoreCase(UpgradeManager.COVER)) {
			for (Object obj : db) {
				deleteMethod.invoke(o, obj);
			}
			for (Object obj : local) {
				insertMethod.invoke(o, obj);
			}
		} else if (rule.equalsIgnoreCase(UpgradeManager.ADD)) {
			create = UpgradeManager.getInsert(local, db, identify);
			for (Object obj : create) {
				insertMethod.invoke(o, obj);
			}
		} else if (rule.equalsIgnoreCase(UpgradeManager.INSERTORUPDATE)) {
			create = UpgradeManager.getInsert(local, db, identify);
			for (Object obj : create) {
				insertMethod.invoke(o, obj);
			}
			update = UpgradeManager.getUpdate(local, db, identify, fields);
			for (Object obj : update) {
				modifyMethod.invoke(o, obj);
			}
		}
	}
	private static List<Object> getUpdate(List<Object> local, List<Object> db, String[] identify, String[] fields) {
		List<Object> update = new ArrayList<Object>();
		boolean modify = false;
		for (int i = 0; i < local.size(); i++) {
			modify = false;
			Map<String, Object> loc = (Map<String, Object>) local.get(i);
			for (int j = 0; j < db.size(); j++) {
				Map<String, Object> dbo = (Map<String, Object>) db.get(j);
				boolean equal = true;
				for (int m = 0; m < identify.length; m++) {
					String locvalue = loc.get(identify[m]).toString();
					String dbvalue = dbo.get(identify[m]).toString();
					if (!locvalue.equals(dbvalue)) {
						equal = false;
						break;
					}
				}
				if (equal) {
					for (int m = 0; m < fields.length; m++) {
						String locvalue = null;
						try {
							locvalue = loc.get(fields[m]).toString();
						} catch (Exception e) {
						}
						String dbvalue = null;
						try {
							dbvalue = dbo.get(fields[m]).toString();
						} catch (Exception e) {
						}
						if (locvalue == null) {
							if (dbvalue == null) {
								continue;
							} else {
								update.add(loc);
								modify = true;
								break;
							}
						} else {
							if (dbvalue == null) {
								update.add(loc);
								modify = true;
								break;
							} else {
								if (!locvalue.equals(dbvalue)) {
									update.add(loc);
									modify = true;
									break;
								}
							}
						}
					}
					if (modify) {
						break;
					}
				}
			}
		}
		return update;
	}
	private static List<Object> getInsert(List<Object> local, List<Object> db, String[] identify) {
		List<Object> create = new ArrayList<Object>();
		boolean have = false;
		for (int i = 0; i < local.size(); i++) {
			have = false;
			Map<String, Object> loc = (Map<String, Object>) local.get(i);
			for (int j = 0; j < db.size(); j++) {
				Map<String, Object> dbo = (Map<String, Object>) db.get(j);
				boolean equal = true;
				for (int m = 0; m < identify.length; m++) {
					String locvalue = loc.get(identify[m]).toString();
					String dbvalue = dbo.get(identify[m]).toString();
					if (!locvalue.equals(dbvalue)) {
						equal = false;
						break;
					}
				}
				if (equal) {
					have = true;
					break;
				}
			}
			if (!have) {
				create.add(loc);
			}
		}
		return create;
	}
	private static List<Object> getInsert(List<Object> local, List<Object> db, List<Field> pklist) throws IllegalArgumentException,
			IllegalAccessException {
		List<Object> create = new ArrayList<Object>();
		boolean have = false;
		for (int i = 0; i < local.size(); i++) {
			have = false;
			Object loc = local.get(i);
			for (int j = 0; j < db.size(); j++) {
				Object dbo = db.get(j);
				boolean equal = true;
				for (int m = 0; m < pklist.size(); m++) {
					String locvalue = pklist.get(m).get(loc).toString();
					String dbvalue = pklist.get(m).get(dbo).toString();
					if (!locvalue.equals(dbvalue)) {
						equal = false;
						break;
					}
				}
				if (equal) {
					have = true;
					break;
				}
			}
			if (!have) {
				create.add(loc);
			}
		}
		return create;
	}
	private static List<Object> getUpdate(List<Object> local, List<Object> db, List<Field> pklist, List<Field> fieldlist)
			throws IllegalArgumentException, IllegalAccessException {
		List<Object> update = new ArrayList<Object>();
		boolean modify = false;
		for (int i = 0; i < local.size(); i++) {
			modify = false;
			Object loc = local.get(i);
			for (int j = 0; j < db.size(); j++) {
				Object dbo = db.get(j);
				boolean equal = true;
				for (int m = 0; m < pklist.size(); m++) {
					String locvalue = pklist.get(m).get(loc).toString();
					String dbvalue = pklist.get(m).get(dbo).toString();
					if (!locvalue.equals(dbvalue)) {
						equal = false;
						break;
					}
				}
				if (equal) {
					for (int m = 0; m < fieldlist.size(); m++) {
						String locvalue = null;
						try {
							locvalue = fieldlist.get(m).get(loc).toString();
						} catch (Exception e) {
						}
						String dbvalue = null;
						try {
							dbvalue = fieldlist.get(m).get(dbo).toString();
						} catch (Exception e) {
						}
						if (locvalue == null) {
							if (dbvalue == null) {
								continue;
							} else {
								update.add(loc);
								modify = true;
								break;
							}
						} else {
							if (dbvalue == null) {
								update.add(loc);
								modify = true;
								break;
							} else {
								if (!locvalue.equals(dbvalue)) {
									update.add(loc);
									modify = true;
									break;
								}
							}
						}
					}
					if (modify) {
						break;
					}
				}
			}
		}
		return update;
	}
	public static String[] getFileds(Class o) {
		Field[] fields = null;
		try {
			fields = o.getDeclaredFields();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		List<String> fieldList = new ArrayList<String>();
		for (int i = 0; i < fields.length; i++) {
			String fieldname = fields[i].getName();
			if (fieldname.equalsIgnoreCase("serialVersionUID")) {
				continue;
			}
			fieldList.add(fieldname);
		}
		String[] fieldnames = new String[fieldList.size()];
		return fieldList.toArray(fieldnames);
	}
}
